﻿using System;
using System.Linq;

namespace Validate.Net
{
    /// <summary>
    /// 校验统一社会信用代码是否合法
    /// </summary>
    public class ValidateSocialCreditCodeAttribute : AbstractValidateAttribute
    {
        /// <summary>
        /// 校验统一社会信用代码是否合法
        /// </summary>
        /// <param name="value"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public override bool Validate(object value, out string msg)
        {
            if (value != null && IsSocialCreditCode(value.ToString()))
            {
                msg = string.Empty;
                return true;
            }
            else
            {
                msg = "校验统一社会信用代码失败";
                return false;
            }
        }

        /// <summary>
        /// 验证规则
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public static bool IsSocialCreditCode(string code)
        {
            if (code.Length != 18) return false;
            code = code.ToUpper();
            int[] factor = { 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28 };
            string str = "0123456789ABCDEFGHJKLMNPQRTUWXY";
            int total = factor.Select((p, i) => p * str.IndexOf(code[i])).Sum();
            int index = total % 31 == 0 ? 0 : (31 - total % 31);
            return str[index] == code.Last();
        }
    }
}
